
class InterceptorManager {
    constructor() {
        this.handlers = [];
    }

    use(fulfilled, rejected) {
        this.handlers.push({
            fulfilled: fulfilled,
            rejected: rejected
        });
    }
}

class Kxios {

    constructor(instanceConfig) {
        this.defaults = instanceConfig;
        this.interceptors = {
            request: new InterceptorManager(),
            response: new InterceptorManager()
        };
    }

    request(config) {
        // 把 request 方法传入的配置项与实例化的时候的配置项进行合并
        config = Object.assign({}, this.defaults, config);

        if (config.method) {
            config.method = config.method.toLowerCase();
        } else if (this.defaults.method) {
            config.method = this.defaults.method.toLowerCase();
        } else {
            config.method = 'get';
        }

        // 任务链（拦截器）

        let chain = [dispatchRequest, undefined];
        let promise = Promise.resolve(config);

        // 执行完下面的foreach 结果 ：chain = [fulfilled[1], rejected[1], fulfilled[0], rejected[0], dispatchRequest, undefined]
        this.interceptors.request.handlers.forEach(handler => {
            chain.unshift(handler.fulfilled, handler.rejected);
        });

        // 执行完下面的foreach 结果 ：chain = [fulfilled[1], rejected[1], fulfilled[0], rejected[0], dispatchRequest, undefined, fulfilled[3], rejected[3], fulfilled[4], rejected[4] ]
        this.interceptors.response.handlers.forEach(handler => {
            chain.push(handler.fulfilled, handler.rejected);
        });

        // promise.then(chain[0], chain[1]);

        while (chain.length) {
            promise = promise.then(chain.shift(), chain.shift());
        }

        // 写法一
        // promise.then().then()

        // 写法二
        // promise.then();
        // promise.then();

        return promise;


        // return dispatchRequest(config);

    }
}

function dispatchRequest(config) {
    console.log('开始发送请求')
    return new Promise(((resolve, reject) => {

        let xhr = new XMLHttpRequest();

        let url = config.baseURL + config.url;

        xhr.open(config.method, url);

        xhr.onload = function() {
            console.log('请求完成了')
            resolve(this.responseText);
        }
        xhr.send();
    }))
}


['delete', 'get', 'head', 'options'].forEach(method => {
    Kxios.prototype[method] = function(url, config) {
        config = Object.assign({}, config, {
            method,
            url: url,
            data: (config || {}).data
        });

        return this.request(config);
    }
})


let defaultConfigs = {
    baseURL: '',
    url: '/'
}


function createInstance(defaultConfig) {
    let context = new Kxios(defaultConfig);

    let instance = Kxios.prototype.request.bind(context);

    for (let method in Kxios.prototype) {
        if (method.toLowerCase() != 'request') {
            instance[method] = Kxios.prototype[method].bind(context);
        }
    }

    for (let attr in context) {
        if (context.hasOwnProperty(attr)) {
            instance[attr] = context[attr];
        }
    }

    return instance;
}

let kxios = new createInstance(defaultConfigs);
